#/* ------------------------------------------------------------------------------
# * Copyright (c) 2006 Novell, Inc. All Rights Reserved.
# *
# *
# * This program is free software; you can redistribute it and/or modify it under
# * the terms of version 2 of the GNU General Public License as published by the
# * Free Software Foundation.
# *
# * This program is distributed in the hope that it will be useful, but WITHOUT
# * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License along with
# * this program; if not, contact Novell, Inc.
# *
# * To contact Novell about this file by physical or electronic mail, you may find
# * current contact information at www.novell.com.
# * ------------------------------------------------------------------------------
#
#
#/**
# * File:           modules/EducationComplex.ycp
# * Package:        YaST Education module
# * Summary:        Complex dialog definitions
# * Authors:        Jeff Shantz <jshantz4@csd.uwo.ca>
# */

################################################################################
# Imports
################################################################################

import EducationAccessTimes
import EducationDialogs
import EducationFiltering
import EducationFirewalling
import EducationGroup
import EducationUser
import EducationWidgets
import gettext
import pprint
import ycp
from ycp import *
  
gettext.install("education")

import re

from YCPDeclarations import YCPDeclare
from EducationHelps import HELPS
from EducationGUIHelper import *

import_module('UI')
import_module("Popup")
import_module("Confirm")
import_module('Label')

ycp.widget_names('Widgets')
import Widgets
from Widgets import *

from ycp import *
import Education
from Education import *

################################################################################
# Functions
################################################################################

#/**
# * Return a modification status
# * @return true if data was modified
# */
def Modified():
  return Education.Modified()

def ReallyAbort():
  return not Education.Modified() or ycp.Popup.ReallyAbort(True)

def PollAbort():
  return ycp.UI.PollInput() == Symbol("abort")

#/**
# * Read settings dialog
# * @return `abort if aborted and `next otherwise
# */
@YCPDeclare("symbol")
def ReadDialog():

  ycp.Wizard.RestoreHelp(HELPS["read"])

  #// Education::SetAbortFunction(PollAbort);
  if not ycp.Confirm.MustBeRoot(): return Symbol("abort")
  
  ret = Education.Read()
  
  if ret:
    return Symbol("next")
  else:
    return Symbol("abort")

#/**
# * Write settings dialog
# * @return `abort if aborted and `next otherwise
# */
@YCPDeclare("symbol")
def WriteDialog():
    
  ycp.Wizard.RestoreHelp(HELPS["write"])
  #// Education::SetAbortFunction(PollAbort);

  ret = Education.Write()
  if ret:
    return Symbol("next")
  else:
    return Symbol("abort")

#/**
# * Intended system usage dialog
# * @return dialog result
# */
@YCPDeclare("symbol")
def SystemUsageDialog():     

  # Wizard caption
  caption = _("Intended System Usage")

  # GUI contents
  contents = \
    VBox(
      Widgets.Label(_("Please select the intended use for this system:")),
      VSpacing(1),
      HVSquash(
        RadioButtonGroup(id('config_type'),
          VBox(
            Left(RadioButton(id("desktop"), 
              _("&Home, classroom, or lab computer"),
              config_equals('config_type', 'desktop'))),
            Left(RadioButton(id("server"), 
              _("&School server"),
              config_equals('config_type', 'server')))
          )
        )
      ),
      VSpacing(1)
    )
    
  ycp.Wizard.SetContentsButtons(caption, contents, HELPS["system_usage"],
    ycp.Label.BackButton(), ycp.Label.NextButton())

  # First step, so disable the back button
  ycp.Wizard.DisableBackButton()

  ret = None

  while True:
       
    ret = ycp.UI.UserInput()
    
    # User clicked and confirmed abort
    if response_was(ret, "abort") and ReallyAbort():
      break

    # User clicked next
    elif response_was(ret, "next"):

      # Get the user's selection
      selection = UI.QueryWidget(id('config_type'), sym('Value'))

      if (selection.value != get_config('config_type')):
        Education.SetModified(True)

      # Store the value selected in the module configuration
      set_config('config_type', selection.value)

      # Return the selection to determine next step
      ret = selection
      break

  return ret

#/**
# * Target age groups dialog
# * @return dialog result
# */
@YCPDeclare("symbol")
def AgeGroupDialog():        

  # Wizard caption
  caption = _("Target Age Groups");

  # GUI contents
  contents = \
    VBox(
      Widgets.Label(_("Please select the primary age group(s) that will use this system:")),
      VSpacing(1),
      HVSquash(
        VBox(
          Left(CheckBox(id('children'), _("&Children (Under 13)"), config_list_has('age_groups', 'children'))),
          Left(CheckBox(id('teenagers'), _("&Teenagers (13 and older)"), config_list_has('age_groups', 'teenagers')))
        )
      ),
      VSpacing(1)
    )

  ycp.Wizard.SetContentsButtons(caption, contents, HELPS["age_groups"],
    ycp.Label.BackButton(), ycp.Label.NextButton())

  ret = None

  while True:

    ret = ycp.UI.UserInput()
        
    # User clicked and confirmed abort
    if response_was(ret, "abort") and ReallyAbort():
      break

    # User clicked back or next
    elif response_was(ret, "next") or response_was(ret, "back"):
      selections = []

      if UI.QueryWidget(id('children'), sym('Value')):
        selections.append('children')

      if UI.QueryWidget(id('teenagers'), sym('Value')):
        selections.append('teenagers')

      if (set(selections) != set(Education.valid_age_groups)):
        Education.SetModified(True)

      set_config('age_groups', selections)
      
      break          

  return ret

#/**
# * Ensures that we have a selected item in a table.  If not, an error
# * message is displayed.
# * @param widget The widget to query
# * @param attribute The attribute of the widget to query
# * @param object The type of object (e.g. user, group, etc.)
# * @param action The action being attempted on the object (e.g. edit, delete, etc.)
# * @return The identifier of the object, if one was selected; otherwise, None
# */
def ensure_selection(widget, attribute, object, action):

  obj = UI.QueryWidget(id(widget), sym(attribute))

  if (obj == None):
    Popup.Error(_("Please select a " + object + " to " + action + "."))
    return None
  else:
    return obj

#/**
# * Groups dialog
# * @return dialog result
# */
@YCPDeclare("symbol")
def GroupsDialog():

  # Wizard caption
  caption = _("Education Groups")

  global edit_group
  global edit_mode  
  
  # Contents of the groups tab
  contents = \
    VBox(
      Table(id('groups_table'), notify_opt(),
      table_header([_("Group"), _("Friendly Name"), _("Age Range"), _("Members")]), EducationGroup.get_groups_table_data()),
      Left(
        HBox(
          PushButton(id('add_group'), opt('key_F3'), Label.AddButton()),
          PushButton(id('edit_group'), opt('key_F4'), Label.EditButton()),
          PushButton(id('delete_group'), opt('key_F5'), Label.DeleteButton()),
          IconButton(id('import_groups'), opt('key_F6'), "icons/22x22/apps/yast-education-fileimport.png", _(" I&mport "))
        )
      )
    )

  ycp.Wizard.SetContentsButtons(caption, contents, HELPS["groups"],
    ycp.Label.BackButton(), ycp.Label.NextButton())

  ret = None

  while True:

    ret = ycp.UI.UserInput()
    
    print ret
    
    if response_was(ret, "delete_group"):
      group_to_delete = ensure_selection('groups_table', 'Value', 'group', 'delete')

      if (group_to_delete == None):
        continue

      # Confirm the delete
      if (Popup.AnyQuestion(Label.WarningMsg(), "Are you sure you wish to delete the selected group?", "Yes", "No", Symbol('focus_no'))):        

        # Delete the group from the configuration
        EducationGroup.delete_group(group_to_delete)
        Education.SetModified(True)

        # Update the table
        UI.ChangeWidget(id("groups_table"), sym('Items'), EducationGroup.get_groups_table_data())

    elif response_was(ret, "import_groups"):

      # Run the import wizard
      EducationDialogs.import_group_wizard()
      
      # Update the table
      UI.ChangeWidget(id("groups_table"), sym('Items'), EducationGroup.get_groups_table_data())
      
    elif response_was(ret, "abort"):

      if ReallyAbort():
        break
      else:
        continue

    elif response_was(ret, "add_group"):

      # We don't want to open the group editor in edit mode
        edit_group = Group()
        edit_mode = False        
        break

    elif response_was(ret, "edit_group") or response_was(ret, "groups_table"):
      
      group_to_edit = ensure_selection('groups_table', 'Value', 'group', 'edit')
      
      # If a group was selected
      if (group_to_edit != None):
        
        # Remember the selected group        
        edit_group = EducationGroup.load_group(group_to_edit)
        edit_group.save_state()
        edit_mode = True        
        
        ret = sym('edit_group')
        break

    elif response_was(ret, "back"):
      break
    elif response_was(ret, "next"):
     
      # Ensure that we have at least one group
      if len(EducationGroup.get_education_groups()) == 0:
        Popup.Error(_("Please add at least one education group."))
      else:        
        break
    
    else:
      y2error("unexpected retcode: %s" % (ret))
      continue

  return ret

@YCPDeclare("symbol")
def UsersDialog():

  global edit_user
  global edit_mode  

  # Wizard caption
  caption = _("User Accounts")

  # Contents of the users tab
  contents = \
    VBox(
      Table(id('users_table'), notify_opt(),
      table_header([_("Username"), _("Full name"), _("Education group"), _("Automatic Login"), _("Enabled")]), EducationUser.get_users_table_data()),
      Left(
        HBox(
          PushButton(id('add_user'), opt('key_F3'), Label.AddButton()),
          PushButton(id('edit_user'), opt('key_F4'), Label.EditButton()),
          PushButton(id('delete_user'), opt('key_F5'), Label.DeleteButton()),
          IconButton(id('import_users'), opt('key_F6'), "icons/22x22/apps/yast-education-fileimport.png", _(" I&mport "))
        )
      )
    )

  ycp.Wizard.SetContentsButtons(caption, contents, HELPS["users"],
    ycp.Label.BackButton(), ycp.Label.NextButton())

  ret = None

  while True:

    ret = ycp.UI.UserInput()
   
    if response_was(ret, "delete_user"):

      user_to_delete = ensure_selection('users_table', 'Value', 'user', 'delete')

      if (user_to_delete == None):
        continue

      # Confirm the delete
      if (Popup.AnyQuestion(Label.WarningMsg(), "Are you sure you wish to delete the selected user?", "Yes", "No", Symbol('focus_no'))):

        # Delete the group from the configuration
        EducationUser.delete_user(user_to_delete)
        Education.SetModified(True)

        # Update the table
        UI.ChangeWidget(id("users_table"), sym('Items'), EducationUser.get_users_table_data())      

    elif response_was(ret, "import_users"):

      # Run the import wizard
      EducationDialogs.import_user_wizard()

      # Update the table
      UI.ChangeWidget(id("users_table"), sym('Items'), EducationUser.get_users_table_data())

    elif response_was(ret, "abort"):

      if ReallyAbort():
        break
      else:
        continue

    elif response_was(ret, "add_user"):

      # We don't want to open the user editor in edit mode
      edit_user = User()
      edit_mode = False
      break

    elif response_was(ret, "edit_user") or response_was(ret, "users_table"):

      user_to_edit = ensure_selection('users_table', 'Value', 'user', 'edit')

      # If a user was selected
      if (user_to_edit != None):

        # Remember the selected user
        edit_user = EducationUser.load_user(user_to_edit)
        edit_mode = True
        edit_user.save_state()
        
        ret = sym('edit_user')
        break

    elif ret == Symbol("next"):

      if not EducationUser.ensure_all_users_have_groups():
        Popup.Error("At least one user has not been assigned to an Education group.\nPlease ensure that each user is assigned to a group and try again.")
        continue
      else:
        break
    elif ret == Symbol("back"):
      break          

  return ret

@YCPDeclare("symbol")
def AddEditGroupDialog():  
  
  global edit_group
  global edit_mode

  group_name_edited = edit_mode
  
  if (edit_mode):
    caption = _("Edit Group")
  else:
    caption = _("Add Group")    

  contents = \
    HVSquash(
      VBox(
        TextEntry(id('friendly_name'), opt('notify'), _("&Friendly Name"), edit_group.friendly_name),
        TextEntry(id('group_name'), opt('notify'), _("&Group Name"), edit_group.name),
        HBox(
          IntField(id('age_from'), _("Age Range &Start"), EducationGroup.MIN_AGE, EducationGroup.MAX_AGE, int(edit_group.age_range_start)),
          IntField(id('age_to'), _("Age Range &End"), EducationGroup.MIN_AGE, EducationGroup.MAX_AGE, int(edit_group.age_range_end))
        ),
        VSpacing(1),
        PushButton(id('advanced'), opt('key_F3'), _("&Advanced Configuration"))
      )
    )

  ycp.Wizard.SetContentsButtons(caption, contents, HELPS["groups"],
    ycp.Label.CancelButton(), ycp.Label.OKButton())

  ycp.Wizard.HideAbortButton()

  ret = None

  while True:    

    ret = ycp.UI.UserInput()

    edit_group.set_friendly_name(UI.QueryWidget(id('friendly_name'), sym('Value')))
    edit_group.set_name(UI.QueryWidget(id('group_name'), sym('Value')))
    edit_group.set_age_range_start(UI.QueryWidget(id('age_from'), sym('Value')))
    edit_group.set_age_range_end(UI.QueryWidget(id('age_to'), sym('Value')))
    
    if ((response_was(ret, "friendly_name")) and (not group_name_edited)):

      name = UI.QueryWidget(Term('id', Symbol('friendly_name')), Symbol('Value'))
      name = re.sub(r'[^a-zA-Z0-9_.-]', '', name)
      UI.ChangeWidget(Term('id', Symbol('group_name')), Symbol('Value'), name.lower())
      edit_group.set_name(UI.QueryWidget(id('group_name'), sym('Value')))

    elif response_was(ret, 'group_name'):

      group_name_edited = (len(UI.QueryWidget(Term('id', Symbol('group_name')), Symbol('Value'))) > 0)

    elif response_was(ret, 'abort'):

      if ReallyAbort():
        break
      else:
        continue

    elif response_was(ret, 'next'):
      
      (is_valid, errors) = edit_group.validate(EducationGroup.get_existing_groups())
      
      if (is_valid):
        edit_group.save()

        if (edit_group.modified):
            Education.SetModified(True)
            
        break

      else:
        Popup.Error(errors[0])

    elif response_was(ret, 'back'):
      edit_group.restore_state()
      break

    elif response_was(ret, 'advanced'):
      break
  
  return ret
                
@YCPDeclare("symbol")
def AdvancedGroupsDialog():

  global edit_group

  caption = _("Advanced Group Configuration")

  contents = VSquash(
    VBox(
      RadioButtonGroup(id('profile_type'),
        VBox(
          Left(RadioButton(Term('id', Symbol('default')), Term('opt', Symbol('notify')), "Use default Sabayon and Kiosk Tool profiles according to the group's age range", edit_group.profile_type == 'default')),
          Left(RadioButton(Term('id', Symbol('none')), Term('opt', Symbol('notify')), "Do not use Sabayon or Kiosk Tool profiles for this group", edit_group.profile_type == 'none')),
          Left(RadioButton(Term('id', Symbol('custom')), Term('opt', Symbol('notify')), "Use custom profiles for this group", edit_group.profile_type == 'custom')),
        )
      ),
      Frame(Term('id', Symbol('custom')), "Custom Profiles",
        VBox(
          HBox(
            TextEntry(Term('id', Symbol('sabayon')), Term('opt', Symbol('hstretch'), Symbol('disabled')), _("&Sabayon profile:"), edit_group.sabayon_profile),
            VBox(
              Widgets.Label(""),
              PushButton(Term('id', Symbol('browse_sabayon')), Term('opt', Symbol('disabled')), _("Browse"))
            )
          ),
          HBox(
            TextEntry(Term('id', Symbol('kiosk')), Term('opt', Symbol('hstretch'), Symbol('disabled')), _("&KDE Kiosk profile:"), edit_group.kiosk_profile),
            VBox(
              Widgets.Label(""),
              PushButton(Term('id', Symbol('browse_kiosk')), Term('opt', Symbol('disabled')), _("Browse"))
            )
          )
        )
      )
    )
  )
  
  ycp.Wizard.SetContentsButtons(caption, contents, "", ycp.Label.CancelButton(), ycp.Label.OKButton())
  ycp.Wizard.HideAbortButton()

  UI.ChangeWidget(Term('id', Symbol('sabayon')), Symbol('Enabled'), edit_group.profile_type == 'custom')
  UI.ChangeWidget(Term('id', Symbol('browse_sabayon')), Symbol('Enabled'), edit_group.profile_type == 'custom')
  UI.ChangeWidget(Term('id', Symbol('kiosk')), Symbol('Enabled'), edit_group.profile_type == 'custom')
  UI.ChangeWidget(Term('id', Symbol('browse_kiosk')), Symbol('Enabled'), edit_group.profile_type == 'custom')
  
  ret = None

  while True:    

    ret = ycp.UI.UserInput()

    print ret

    if response_was(ret, 'default') or response_was(ret, 'none'):

      # Disable all widgets
      UI.ChangeWidget(Term('id', Symbol('sabayon')), Symbol('Enabled'), False)
      UI.ChangeWidget(Term('id', Symbol('browse_sabayon')), Symbol('Enabled'), False)
      UI.ChangeWidget(Term('id', Symbol('kiosk')), Symbol('Enabled'), False)
      UI.ChangeWidget(Term('id', Symbol('browse_kiosk')), Symbol('Enabled'), False)

    elif response_was(ret, 'custom'):

      # Enable all widgets
      UI.ChangeWidget(Term('id', Symbol('sabayon')), Symbol('Enabled'), True)
      UI.ChangeWidget(Term('id', Symbol('browse_sabayon')), Symbol('Enabled'), True)
      UI.ChangeWidget(Term('id', Symbol('kiosk')), Symbol('Enabled'), True)
      UI.ChangeWidget(Term('id', Symbol('browse_kiosk')), Symbol('Enabled'), True)  

    elif response_was(ret, "back"):
      break
      
    elif response_was(ret, "next"):

      edit_group.profile_type = UI.QueryWidget(id('profile_type'), sym('Value')).value
      edit_group.sabayon_profile = UI.QueryWidget(id('sabayon'), sym('Value')).strip()
      edit_group.kiosk_profile = UI.QueryWidget(id('kiosk'), sym('Value')).strip()
     
      if (edit_group.profile_type == 'custom'):
     
        if (not EducationGroup.valid_profile(edit_group.sabayon_profile)):
          Popup.Error("The specified Sabayon profile does not exist or is not a file.")
          continue
        elif (not EducationGroup.valid_profile(edit_group.kiosk_profile)):
          Popup.Error("The specified Kiosk Tool profile does not exist or is not a file.")
          continue
    
      break

    elif response_was(ret, "browse_sabayon"):

      file = UI.AskForExistingFile("/etc", "*.*", "Select the Sabayon profile to use")

      if (file):
        UI.ChangeWidget(id('sabayon'), sym('Value'), file)

    elif response_was(ret, "browse_kiosk"):

      file = UI.AskForExistingFile("/etc", "*.*", "Select the Kiosk Tool profile to use")

      if (file):
        UI.ChangeWidget(id('kiosk'), sym('Value'), file)

  return ret


@YCPDeclare("symbol")
def AddEditUsersDialog():

  global edit_user
  global edit_mode  

  username_edited = edit_mode
  password_edited = False

  if (edit_mode):
    caption = _("Edit User")
  else:
    caption = _("Add User")    

  contents = \
    HVSquash(
      VBox(
        TextEntry(id('full_name'), opt('notify'), _("&Full name:"), edit_user.full_name),
        TextEntry(id('username'), opt('notify'), _("&Username:"), edit_user.username or ''),
        Password(id('password'), opt('notify'), _("&Password:"), edit_user.password or ''),
        Password(id('confirm_password'), opt('notify'), _("&Confirm password:"), edit_user.password or ''),
        Left(ComboBox(id("group"), _("&Education group:"), EducationGroup.get_education_groups())),
        CheckBox(id('auto_login'), _("&Automatic login"), edit_user.auto_login),
        CheckBox(id('disable_login'), _("&Disable user login"), (not edit_user.enabled))
      )
    )

  ycp.Wizard.SetContentsButtons(caption, contents, "",
    ycp.Label.CancelButton(), ycp.Label.OKButton())

  if (edit_user.group) and (edit_user.group.name in EducationGroup.get_education_groups()):
    UI.ChangeWidget(id('group'), Symbol('Value'), edit_user.group and edit_user.group.name)
    
  ret = None

  while True:

    ret = ycp.UI.UserInput()

    print ret

    if ((response_was(ret, "full_name")) and (not username_edited)):

      name = UI.QueryWidget(Term('id', Symbol('full_name')), Symbol('Value'))
      name = re.sub(r'[^a-zA-Z0-9_.-]', '', name)
      UI.ChangeWidget(Term('id', Symbol('username')), Symbol('Value'), name.lower())    

    elif (response_was(ret, 'username')):

      username_edited = (len(UI.QueryWidget(id('username'), sym('Value'))) > 0)
    
    elif (response_was(ret, 'password')):    

      password_edited = True

    elif (response_was(ret, 'confirm_password')):

      password_edited = True
      
    elif ret == Symbol("abort"):

      if ReallyAbort():
        break
      else:
        continue

    elif response_was(ret, "next"):

      edit_user.set_full_name(UI.QueryWidget(id('full_name'), sym('Value')))
      edit_user.set_username(UI.QueryWidget(id('username'), sym('Value')))

      new_group = UI.QueryWidget(id('group'), sym('Value'))

      if (edit_user.is_new) or (edit_user.group == None) or (new_group != edit_user.group.name):
        edit_user.set_group(new_group)

      edit_user.set_auto_login(UI.QueryWidget(id('auto_login'), sym('Value')))
      edit_user.set_enabled(not UI.QueryWidget(id('disable_login'), sym('Value')))

      (is_valid, errors) = edit_user.validate_user(EducationUser.get_existing_users(), EducationGroup.get_education_groups())

      if (is_valid):

        if ((password_edited) and (UI.QueryWidget(id('password'), sym('Value')) != UI.QueryWidget(id('confirm_password'), sym('Value')))):
          Popup.Error("Password and confirm password fields do not match.")
          continue
        elif password_edited or edit_user.is_new:

          pwd = UI.QueryWidget(id('password'), sym('Value'))

          if (pwd == None) or (pwd == ''):
           response = Popup.AnyQuestion(Label.WarningMsg(), "You have not entered a password for this user, which will allow anyone to login\nusing this account.  Are you sure you wish to save this user with no password?", "Yes", "No", sym('focus_no'))

           if not response:
             continue

          edit_user.set_password(pwd)

        edit_user.save()

        if (edit_user.modified):
            Education.SetModified(True)

        break

      else:
        Popup.Error(errors[0])

    elif ret == Symbol("back"):
      edit_user.restore_state()
      break
    
  return ret

#/**
# * Web filtering dialog
# * @return dialog result
# */
@YCPDeclare("symbol")
def WebFilteringDialog():

  # Wizard caption
  caption = _("Web Filtering")

  # Contents of the users tab
  contents = \
    CheckBoxFrame(id('global_filtering'), opt('notify'), "Enable web content filtering on this system", Education.get_config('global_filtering_enabled'),
      VBox(
        Table(id('filter_table'), notify_opt(),
          table_header([_("Group"), _("Filter Level")]), EducationFiltering.get_group_filtering_table_data()), 
        Left(
          HBox(
            PushButton(id('edit_filter'), opt('key_F4'), Label.EditButton()),
          )
        )
      )
    )

  ycp.Wizard.SetContentsButtons(caption, contents, "",
    ycp.Label.BackButton(), ycp.Label.NextButton())

  ycp.Wizard.RestoreAbortButton()
  
  ret = None

  while True:

    ret = ycp.UI.UserInput()
    print ret

    if response_was(ret, "abort"):
      if ReallyAbort():
        break
      else:
        continue

    elif response_was(ret, "edit_filter") or response_was(ret, "filter_table"):

      group_to_edit = ensure_selection('filter_table', 'Value', 'group', 'filter')

      # If a group was selected
      if (group_to_edit != None):

        global edit_filter
        global edit_group
        
        # Remember the selected filter
        edit_filter = EducationFiltering.get_filter_settings_for_group(group_to_edit)
        edit_group = group_to_edit
        edit_filter.save_state()

        ret = sym('edit_filter')
        break

    elif response_was(ret, 'global_filtering'):
      Education.set_config('global_filtering_enabled', UI.QueryWidget(id('global_filtering'), sym('Value')))
      Education.SetModified(True)
      
    elif ret == Symbol("next") or ret == Symbol("back"):
      break

  return ret

#/**
# * Edit web filter dialog
# * @return dialog result
# */
@YCPDeclare("symbol")
def EditWebFilterDialog():

  # Wizard caption
  caption = _("Edit Web Filtering")

  global edit_filter
  global edit_group
  print edit_filter.banned_topics

  filtering_enabled = edit_filter.enabled
  filter_tolerance_level = edit_filter.tolerance
  banned_items = list(edit_filter.banned_topics)
  filter_level = EducationFiltering.get_filter_preset_name(filter_tolerance_level, banned_items)
  whitelist = list(edit_filter.whitelist)
  whitelist_mode = edit_filter.whitelist_mode
  blacklist = list(edit_filter.blacklist)
  keywords = list(edit_filter.banned_keywords)
  extensions = list(edit_filter.banned_extensions)

  tabs = [tab('filter_tab', _("&Filter settings")),
    tab('whitelist_tab', _("&Allowed sites")),
    tab('blacklist_tab', _("Banned sites")),
    tab('keyword_tab', _("Banned keywords")),
    tab('extension_tab', _("Banned &file extensions"))
  ]
  
  filter_selector = EducationWidgets.Selector("filter", "Allowed Content", "Restricted Content")

  if UI.HasSpecialWidget(sym('Slider')):
    filter_tolerance = Slider(id('filter_tolerance'), opt('notify'), "Filter tolerance:", EducationFiltering.MIN_TOLERANCE, EducationFiltering.MAX_TOLERANCE, filter_tolerance_level)
  else:
    filter_tolerance = IntField(id('filter_tolerance'), opt('notify'), "Filter tolerance:", EducationFiltering.MIN_TOLERANCE, EducationFiltering.MAX_TOLERANCE, filter_tolerance_level)
  
  filter_tab_contents = \
    VBox(
      CheckBoxFrame(id('enable_filtering'), opt('notify'), "Enable filtering for this group", filtering_enabled,
        HBox(
          VBox(
            Left(ComboBox(id('filter_preset'), opt('notify'), "Filter preset:", EducationFiltering.get_filter_preset_list())),
            HStretch(),
            Left(HSquash(Left(filter_tolerance)))
          ),
          HStretch()
        )
      ),
      Frame(id('content_restrictions'), "Content Restrictions",
        VBox(
          filter_selector.get_term()            
        )
      )
    )
           
  whitelist_tab_contents = \
    VBox(
      Frame(id('whitelist_new_site'), "Allow new site",
        VBox(
          TextEntry(id('whitelist_site'), opt('hstretch'), _("&Domain, IP address, or URL to allow:"), ""),
          RadioButtonGroup(id('whitelist_granularity'),
            HBox(
              VBox(
                Left(RadioButton(id('whitelist_page'), '&Allow only this specific address/page', True)),
                Left(RadioButton(id('whitelist_entire'), '&Allow this entire site', False))
              ),
              PushButton(id('whitelist_add'), opt('key_F3'), Label.AddButton())
            )
          ),
        )
      ),
      Frame(id('whitelist_allowed_sites'), "Allowed sites",
        VBox(
          RadioButtonGroup(id('whitelist_mode'),
            VBox(
              Left(RadioButton(id('whitelist_normal'), opt('notify'), '&Always allow access to the following sites (recommended)', whitelist_mode == 'normal')),
              Left(RadioButton(id('whitelist_only'), opt('notify'), '&Allow access to only the following sites', whitelist_mode == 'only'))
            )
          ),
          SelectionBox(id('whitelist_site_list'), _("Allowed sites list:"), whitelist),
          Left(
            HBox(
              PushButton(id('whitelist_delete'), opt('key_F5'), Label.DeleteButton())
            )
          )
        )
      )
    )
    
  blacklist_tab_contents = \
    VBox(
      Frame(id('blacklist_new_site'), "Ban new site",
        VBox(
          TextEntry(id('blacklist_site'), opt('hstretch'), _("&Domain, IP address, or URL to ban:"), ""),
          RadioButtonGroup(id('blacklist_granularity'),
            HBox(
              VBox(
                Left(RadioButton(id('blacklist_page'), '&Ban only this specific address/page', True)),
                Left(RadioButton(id('blacklist_entire'), '&Ban this entire site', False))
              ),
              PushButton(id('blacklist_add'), opt('key_F3'), Label.AddButton())
            )
          ),
        )
      ),
      Frame(id('blacklist_allowed_sites'), "Banned sites",
        VBox(
          SelectionBox(id('blacklist_site_list'), _("Banned sites list:"), blacklist),
          Left(
            HBox(
              PushButton(id('blacklist_delete'), opt('key_F5'), Label.DeleteButton())
            )
          )
        )
      )
    )
    
  keyword_tab_contents = \
    VBox(
      Frame(id('keyword_new'), "Ban new keyword/phrase",
        HBox(
          TextEntry(id('keyword'), opt('hstretch'), _("&Keyword/phrase to ban:"), ""),
          VBox(
            Widgets.Label(""),
            PushButton(id('add_keyword'), opt('key_F3'), Label.AddButton())
          )
        )
      ),
      Frame(id('banned_keywords'), "Banned keywords/phrases",
        VBox(
          SelectionBox(id('keyword_list'), _("Banned keyword/phrase list:"), keywords),
          Left(
            HBox(
              PushButton(id('delete_keyword'), opt('key_F5'), Label.DeleteButton())
            )
          )
        )
      )
    )  

  extension_tab_contents = \
    VBox(
      Frame(id('extension_new'), "Ban new file extension",
        HBox(
          TextEntry(id('extension'), opt('hstretch'), _("&File extension to ban:"), ""),
          VBox(
            Widgets.Label(""),
            PushButton(id('add_extension'), opt('key_F3'), Label.AddButton())
          )
        )
      ),
      Frame(id('banned_extensions'), "Banned extensions",
        VBox(
          SelectionBox(id('extension_list'), _("Banned file extension list:"), extensions),
          Left(
            HBox(
              PushButton(id('delete_extension'), opt('key_F5'), Label.DeleteButton())
            )
          )
        )
      )
    )


  contents = \
    DumbTab(id('tab_widget'), tabs,
      ReplacePoint(id('tab_contents'), filter_tab_contents))

  ycp.Wizard.SetContentsButtons(caption, contents, "",
    ycp.Label.CancelButton(), ycp.Label.OKButton())

  ycp.Wizard.HideAbortButton()
  
  UI.ChangeWidget(id('content_restrictions'), sym('Enabled'), filtering_enabled)
  UI.ChangeWidget(id('filter_preset'), sym('Value'), filter_level)      
  filter_selector.set_available_items(EducationFiltering.get_filter_categories())
  filter_selector.set_selected_items(banned_items)
  
  ret = None

  while True:

    ret = ycp.UI.UserInput()
    print ret

    if response_was(ret, 'filter_tab'):
      
      UI.ReplaceWidget(Symbol('tab_contents'), filter_tab_contents)
      UI.ChangeWidget(id('filter_preset'), sym('Value'), filter_level)      
      filter_selector.update_widgets()
      UI.ChangeWidget(id('filter_tolerance'), sym('Value'), edit_filter.tolerance)
      UI.ChangeWidget(id('enable_filtering'), sym('Value'), edit_filter.enabled)
      UI.ChangeWidget(id('content_restrictions'), sym('Enabled'), edit_filter.enabled)
      
    elif response_was(ret, "whitelist_tab"):

      UI.ReplaceWidget(Symbol('tab_contents'), whitelist_tab_contents)
      UI.ChangeWidget(id('whitelist_new_site'), sym('Enabled'), edit_filter.enabled)
      UI.ChangeWidget(id('whitelist_allowed_sites'), sym('Enabled'), edit_filter.enabled)
      UI.ChangeWidget(id('whitelist_site_list'), sym('Items'), list(edit_filter.whitelist))
      
      if (edit_filter.whitelist_mode == 'normal'):
        UI.ChangeWidget(id('whitelist_normal'), sym('Value'), True)
      else:
        UI.ChangeWidget(id('whitelist_only'), sym('Value'), True)

    elif response_was(ret, "blacklist_tab"):

      UI.ReplaceWidget(Symbol('tab_contents'), blacklist_tab_contents)
      UI.ChangeWidget(id('blacklist_new_site'), sym('Enabled'), edit_filter.enabled)
      UI.ChangeWidget(id('blacklist_allowed_sites'), sym('Enabled'), edit_filter.enabled)
      UI.ChangeWidget(id('blacklist_site_list'), sym('Items'), list(edit_filter.blacklist))
      
    elif response_was(ret, "keyword_tab"):

      UI.ReplaceWidget(Symbol('tab_contents'), keyword_tab_contents)
      UI.ChangeWidget(id('keyword_new'), sym('Enabled'), edit_filter.enabled)
      UI.ChangeWidget(id('banned_keywords'), sym('Enabled'), edit_filter.enabled)
      UI.ChangeWidget(id('keyword_list'), sym('Items'), (edit_filter.banned_keywords))

    elif response_was(ret, "extension_tab"):

      UI.ReplaceWidget(Symbol('tab_contents'), extension_tab_contents)
      UI.ChangeWidget(id('extension_new'), sym('Enabled'), filtering_enabled)
      UI.ChangeWidget(id('banned_extensions'), sym('Enabled'), filtering_enabled)
      UI.ChangeWidget(id('extension_list'), sym('Items'), extensions)

    elif response_was(ret, 'filter_preset'):
        
      filter_level = UI.QueryWidget(id('filter_preset'), sym('Value'))

      if (filter_level != 'Custom'):

        (filter_tolerance_level, topics) = EducationFiltering.get_filter_preset_settings(filter_level)
        UI.ChangeWidget(id('filter_tolerance'), sym('Value'), filter_tolerance_level)        
        edit_filter.set_tolerance(filter_tolerance_level)
              
        for topic in list(edit_filter.banned_topics):          
          if not topic in topics:            
            edit_filter.remove_banned_topic(topic)
            
        for topic in topics:
          edit_filter.add_banned_topic(topic)

        filter_selector.set_selected_items(list(edit_filter.banned_topics))
    
    elif response_was(ret, 'filter_tolerance'):

      filter_tolerance_level = UI.QueryWidget(id('filter_tolerance'), sym('Value'))
      edit_filter.set_tolerance(filter_tolerance_level)
      filter_level = EducationFiltering.get_filter_preset_name(filter_tolerance_level, edit_filter.banned_topics)
      UI.ChangeWidget(id('filter_preset'), sym('Value'), filter_level)
      
    elif response_was(ret, 'filter_remove_all'):

      removed = filter_selector.remove_all()

      for topic in removed:
        edit_filter.remove_banned_topic(topic)

      filter_level = EducationFiltering.get_filter_preset_name(edit_filter.tolerance, edit_filter.banned_topics)
      UI.ChangeWidget(id('filter_preset'), sym('Value'), filter_level)            

    elif response_was(ret, 'filter_add_all'):

      added = filter_selector.add_all()

      for topic in added:
        edit_filter.add_banned_topic(topic)

      filter_level = EducationFiltering.get_filter_preset_name(edit_filter.tolerance, edit_filter.banned_topics)
      UI.ChangeWidget(id('filter_preset'), sym('Value'), filter_level)           

    elif response_was(ret, 'filter_remove'):

      removed = filter_selector.remove()

      if (removed):
        edit_filter.remove_banned_topic(removed)

      filter_level = EducationFiltering.get_filter_preset_name(edit_filter.tolerance, edit_filter.banned_topics)
      UI.ChangeWidget(id('filter_preset'), sym('Value'), filter_level)  

    elif response_was(ret, 'filter_add'):

      added = filter_selector.add()

      if (added):
        edit_filter.add_banned_topic(added)

      filter_level = EducationFiltering.get_filter_preset_name(edit_filter.tolerance, edit_filter.banned_topics)
      UI.ChangeWidget(id('filter_preset'), sym('Value'), filter_level)      

    elif response_was(ret, 'enable_filtering'):
      
      filtering_enabled = (UI.QueryWidget(id('enable_filtering'), sym('Value')))
      UI.ChangeWidget(id('content_restrictions'), sym('Enabled'), filtering_enabled)
      edit_filter.set_enabled(filtering_enabled)
      
    elif response_was(ret, 'whitelist_add'):

      site = UI.QueryWidget(id('whitelist_site'), sym('Value'))
      mode = UI.QueryWidget(id('whitelist_granularity'), sym('Value'))

      if (mode == sym('whitelist_page')):
        site_to_add = EducationFiltering.parse_url(site)
      else:        
        site_to_add = EducationFiltering.parse_domain(site)

      if (not site_to_add):
        Popup.Error("Invalid site entered.  Please enter a valid hostname, IP address, or URL.")
      elif site_to_add in edit_filter.whitelist:
        Popup.Error("The specified site is already allowed.")
        UI.ChangeWidget(id('whitelist_site'), sym('Value'), "")
      else:
        edit_filter.add_whitelist_site(site_to_add)
        UI.ChangeWidget(id('whitelist_site_list'), sym('Items'), list(edit_filter.whitelist))
        UI.ChangeWidget(id('whitelist_site'), sym('Value'), "")
    
    elif response_was(ret, 'whitelist_delete'):

      item = UI.QueryWidget(id('whitelist_site_list'), sym('CurrentItem'))

      if (item):
        if Popup.AnyQuestion(Label.WarningMsg(), "Are you sure you wish to delete the selected site?", "Yes", "No", Symbol('focus_no')):
          edit_filter.remove_whitelist_site(item)
          UI.ChangeWidget(id('whitelist_site_list'), sym('Items'), list(edit_filter.whitelist))
      else:
        Popup.Error("Please select a site to delete.")

    elif response_was(ret, 'whitelist_normal'):
      edit_filter.set_whitelist_mode('normal')

    elif response_was(ret, 'whitelist_only'):
      edit_filter.set_whitelist_mode('only')

    elif response_was(ret, 'blacklist_add'):

      site = UI.QueryWidget(id('blacklist_site'), sym('Value'))
      mode = UI.QueryWidget(id('blacklist_granularity'), sym('Value'))

      if (mode == sym('blacklist_page')):
        site_to_add = EducationFiltering.parse_url(site)
      else:
        site_to_add = EducationFiltering.parse_domain(site)

      if (not site_to_add):
        Popup.Error("Invalid site entered.  Please enter a valid hostname, IP address, or URL.")
      elif site_to_add in edit_filter.blacklist:
        Popup.Error("The specified site is already banned.")
        UI.ChangeWidget(id('blacklist_site'), sym('Value'), "")
      else:
        edit_filter.add_blacklist_site(site_to_add)
        UI.ChangeWidget(id('blacklist_site_list'), sym('Items'), list(edit_filter.blacklist))
        UI.ChangeWidget(id('blacklist_site'), sym('Value'), "")     
        
    elif response_was(ret, 'blacklist_delete'):

      item = UI.QueryWidget(id('blacklist_site_list'), sym('CurrentItem'))

      if (item):
        if Popup.AnyQuestion(Label.WarningMsg(), "Are you sure you wish to delete the selected site?", "Yes", "No", Symbol('focus_no')):
          edit_filter.remove_blacklist_site(item)
          UI.ChangeWidget(id('blacklist_site_list'), sym('Items'), list(edit_filter.blacklist))
      else:
        Popup.Error("Please select a site to delete.")

    elif response_was(ret, 'add_keyword'):

      keyword = UI.QueryWidget(id('keyword'), sym('Value'))

      if ((not keyword) or re.match("^\s*$", keyword)):
        Popup.Error("Please enter a keyword to ban.")
      elif keyword in edit_filter.banned_keywords:
        Popup.Error("The specified keyword is already banned.")
        UI.ChangeWidget(id('keyword'), sym('Value'), "")
      else:
        edit_filter.add_banned_keyword(keyword)
        UI.ChangeWidget(id('keyword_list'), sym('Items'), list(edit_filter.banned_keywords))
        UI.ChangeWidget(id('keyword'), sym('Value'), "")

    elif response_was(ret, 'delete_keyword'):

      item = UI.QueryWidget(id('keyword_list'), sym('CurrentItem'))

      if (item):
        if Popup.AnyQuestion(Label.WarningMsg(), "Are you sure you wish to delete the selected keyword?", "Yes", "No", Symbol('focus_no')):
          edit_filter.remove_banned_keyword(item)
          UI.ChangeWidget(id('keyword_list'), sym('Items'), list(edit_filter.banned_keywords))
      else:
        Popup.Error("Please select a keyword to delete.")

    elif response_was(ret, 'add_extension'):

      extension = UI.QueryWidget(id('extension'), sym('Value'))

      #TODO: Lookup a proper regex for a file extension -- should probably consist only of valid URL characters since Dansguardian file extension blocking is done by examining the file extension in the URL
      if ((not extension) or (re.match("^\s*$", extension)) or (not re.match("^.?[a-zA-Z0-9+-]+$", extension))):
        Popup.Error("Please enter a valid extension to ban.")
      else:
        extension = re.sub("^\.", "", extension)
        UI.ChangeWidget(id('extension'), sym('Value'), "")

        if extension in edit_filter.banned_extensions:
          Popup.Error("The specified extension is already banned.")          
        else:
          edit_filter.add_banned_extension(extension)
          UI.ChangeWidget(id('extension_list'), sym('Items'), list(edit_filter.banned_extensions))

    elif response_was(ret, 'delete_extension'):

      extension = UI.QueryWidget(id('extension_list'), sym('CurrentItem'))

      if (extension):
        if Popup.AnyQuestion(Label.WarningMsg(), "Are you sure you wish to delete the selected extension?", "Yes", "No", Symbol('focus_no')):
          edit_filter.remove_banned_extension(extension)
          UI.ChangeWidget(id('extension_list'), sym('Items'), list(edit_filter.banned_extensions))
      else:
        Popup.Error("Please select an extension to delete.")

    elif response_was(ret, "abort"):

      if ReallyAbort():
        break
      else:
        continue

    elif ret == Symbol("next"):

      if (edit_filter.modified):
          Education.SetModified(True)
          
      break
      
    elif ret == Symbol("back"):
      edit_filter.restore_state()
      
      break

  return ret

#/**
# * Access time restrictions dialog
# * @return dialog result
# */
@YCPDeclare("symbol")
def AccessTimeDialog():

  # Wizard caption
  caption = _("Access Time Restrictions")
  
  # Contents of the users tab
  contents = \
    VBox(
      Table(id('restrictions_table'), notify_opt(),
        table_header([_("Group"), _("Filter Level")]), []),
      Left(
        HBox(
          PushButton(id('edit_restrictions'), opt('key_F4'), Label.EditButton()),
        )
      )
    )
  
  ycp.Wizard.SetContentsButtons(caption, contents, "",
    ycp.Label.BackButton(), ycp.Label.NextButton())

  ycp.Wizard.RestoreAbortButton()

  UI.ChangeWidget(id('restrictions_table'), sym('Items'), EducationAccessTimes.get_all_groups_table_data())
  ret = None

  while True:

    ret = ycp.UI.UserInput()
    print ret

    if response_was(ret, "abort"):
      if ReallyAbort():
        break
      else:
        continue

    elif response_was(ret, "edit_restrictions") or response_was(ret, "restrictions_table"):

      group_to_edit = ensure_selection('restrictions_table', 'Value', 'group', 'restrict')

      # If a group was selected
      if (group_to_edit != None):
        
        global edit_restrictions

        # Remember the selected group
        edit_restrictions = get_restrictions_for_group(group_to_edit)
        edit_restrictions.save_state()

        ret = sym('edit_restrictions')
        break

    elif ret == Symbol("next") or ret == Symbol("back"):
      break

  return ret

#/**
# * Edit access time restrictions dialog
# * @return dialog result
# */
@YCPDeclare("symbol")
def EditAccessTimeRestrictions():
  caption = _("Edit Access Time Restrictions")

  global edit_restrictions

  hours = []

  for i in range(0, 24):
    hours.append(str(i).rjust(2, '0'))

  minutes = []

  for i in range(0, 60):
    minutes.append(str(i).rjust(2, '0'))

  contents = \
    VBox(
      CheckBoxFrame(id('enable_restrictions'), opt('notify'), "Enable access time restrictions for group", edit_restrictions.enabled,
        VBox(
          Left(Widgets.Label("Access Time Restrictions:")),
          Table(id('access_table'), opt('notify'),
            Term('header', _("Day"), _("Access Allowed"), _("Allowed Time Range")), [])
        )
      ),
      Frame(id('edit_restrictions'), "Edit restriction",
        VBox(
          Left(ComboBox(id('restriction_day'), opt('notify'), "Edit restriction for:", ["All days", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"])),
          VSpacing(0.5),
          Left(Widgets.Label("Restriction:")),
          RadioButtonGroup(id('restriction'), opt('notify'),
            VBox(
              Left(RadioButton(id("access_allowed"), opt('notify'), _("&Allow access all day"), True)),
              Left(
                HSquash(
                  HBox(
                    Left(RadioButton(id("access_between"), opt('notify'), _("&Allow access between "), False)),
                    ComboBox(id('start_hour'), "", hours),
                    Widgets.Label(id('start_colon'), ":"),
                    ComboBox(id('start_min'), "", minutes),
                    HSpacing(1),
                    Widgets.Label(id('and_label'), "and"),
                    HSpacing(1),
                    ComboBox(id('end_hour'), "", hours),
                    Widgets.Label(id('end_colon'), ":"),
                    ComboBox(id('end_min'), "", minutes),
                  )
                )
              ),
              Left(RadioButton(id("access_denied"), opt('notify'), _("&Do not allow access at any time"), False)),
            )
          ),
          Left(PushButton(id('apply_restriction'), "Apply"))
        )
      )
    )

  ycp.Wizard.HideAbortButton()

  ycp.Wizard.SetContentsButtons(caption, contents, "",
    ycp.Label.CancelButton(), ycp.Label.OKButton())

  restrictions_enabled = (UI.QueryWidget(id('enable_restrictions'), sym('Value')))
  UI.ChangeWidget(id('edit_restrictions'), sym('Enabled'), restrictions_enabled)
  UI.ChangeWidget(id('access_table'), sym('Items'), edit_restrictions.get_table_data())

  for widget in ['start_hour', 'start_colon', 'start_min', 'and_label', 'end_hour', 'end_colon', 'end_min']:
    UI.ChangeWidget(id(widget), sym('Enabled'), False)

  ret = None

  while True:

    ret = ycp.UI.UserInput()

    print ret

    if response_was(ret, "enable_restrictions"):
      
      edit_restrictions.set_enabled(UI.QueryWidget(id('enable_restrictions'), sym('Value')))
      UI.ChangeWidget(id('edit_restrictions'), sym('Enabled'), edit_restrictions.enabled)

    elif response_was(ret, "access_allowed") or response_was(ret, "access_between") or response_was(ret, "access_denied"):
      
      for widget in ['start_hour', 'start_colon', 'start_min', 'and_label', 'end_hour', 'end_colon', 'end_min']:
        UI.ChangeWidget(id(widget), sym('Enabled'), UI.QueryWidget(id('access_between'), sym('Value')))

    elif response_was(ret, "access_table") or response_was(ret, "restriction_day"):
     
      if response_was(ret, "access_table"):
        day = UI.QueryWidget(id('access_table'), sym('CurrentItem'))
      else:
        day = UI.QueryWidget(id('restriction_day'), sym('Value'))

      if day == "All days":
        continue

      for widget in ['start_hour', 'start_colon', 'start_min', 'and_label', 'end_hour', 'end_colon', 'end_min']:
        UI.ChangeWidget(id(widget), sym('Enabled'), False)

      UI.ChangeWidget(id('restriction_day'), sym('Value'), day)
      
      if edit_restrictions.allow_access_on(day):

        if edit_restrictions.start_time_on(day) == edit_restrictions.end_time_on(day):
          UI.ChangeWidget(id('access_allowed'), sym('Value'), True)

        else:

          UI.ChangeWidget(id('access_between'), sym('Value'), True)
          UI.ChangeWidget(id('start_hour'), sym('Value'), str(edit_restrictions.get_start_hour(day)).rjust(2, '0'))
          UI.ChangeWidget(id('start_min'), sym('Value'), str(edit_restrictions.get_start_minute(day)).rjust(2, '0'))
          UI.ChangeWidget(id('end_hour'), sym('Value'), str(edit_restrictions.get_end_hour(day)).rjust(2, '0'))
          UI.ChangeWidget(id('end_min'), sym('Value'), str(edit_restrictions.get_end_minute(day)).rjust(2, '0'))

          for widget in ['start_hour', 'start_colon', 'start_min', 'and_label', 'end_hour', 'end_colon', 'end_min']:
            UI.ChangeWidget(id(widget), sym('Enabled'), True)
      else:

        UI.ChangeWidget(id('access_denied'), sym('Value'), True)      
      
    elif response_was(ret, "apply_restriction"):

      if UI.QueryWidget(id('access_allowed'), sym('Value')):

        allow_access = True
        start_time = "00:00"
        end_time = "00:00"

      elif UI.QueryWidget(id('access_between'), sym('Value')):

        allow_access = True

        start_hour = UI.QueryWidget(id('start_hour'), sym('Value'))
        start_min = UI.QueryWidget(id('start_min'), sym('Value'))
        start_time = start_hour + ":" + start_min

        end_hour = UI.QueryWidget(id('end_hour'), sym('Value'))
        end_min = UI.QueryWidget(id('end_min'), sym('Value'))
        end_time = end_hour + ":" + end_min

        if (start_time == end_time):
          Popup.Error("Start and end times must differ.")
          continue

        if (((int(start_hour) == int(end_hour)) and (int(end_min) < int(start_min))) or (int(start_hour) > int(end_hour))):
          temp = end_time
          end_time = start_time
          start_time = temp
                
      else:
        allow_access = False
        start_time = "00:00"
        end_time = "00:00"

      day = UI.QueryWidget(id('restriction_day'), sym('Value'))

      if (day == "All days"):
        days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
      else:
        days = [day]

      for day in days:
        edit_restrictions.set_allowed_on(day, allow_access)
        edit_restrictions.set_start_time_on(day, start_time)
        edit_restrictions.set_end_time_on(day, end_time)

      # Update the table     
      UI.ChangeWidget(id("access_table"), sym('Items'), edit_restrictions.get_table_data())
      UI.ChangeWidget(id("restriction_day"), sym('Value'), "All days")

      for widget in ['start_hour', 'start_colon', 'start_min', 'and_label', 'end_hour', 'end_colon', 'end_min']:
        UI.ChangeWidget(id(widget), sym('Enabled'), False)

      UI.ChangeWidget(id('access_allowed'), sym('Value'), True)
      
    elif response_was(ret, "next"):

      if (edit_restrictions.modified):
          Education.SetModified(True)
          
      break
      
    elif ret == Symbol("back"):
      edit_restrictions.restore_state()
      break

  return ret

#/**
# * Firewall dialog
# * @return dialog result
# */
@YCPDeclare("symbol")
def FirewallDialog():

  caption = _("Firewall Configuration")

  protocol_selector = EducationWidgets.Selector("protocol", "All Protocols", "Blocked Protocols")

  contents = VBox(
    Frame("Firewall Configuration",
      VBox(
        Left(ComboBox(id("group"), opt('notify'), _("&Edit filtering options for group"), EducationGroup.get_education_groups())),
        protocol_selector.get_term()
      )
    )
  )

  ycp.Wizard.SetContentsButtons(caption, contents, "",
    ycp.Label.BackButton(), ycp.Label.NextButton())

  protocol_selector.set_available_items(EducationFirewalling.get_protocols_list())

  group = UI.QueryWidget(id('group'), sym('Value'))
  rules = EducationFirewalling.get_firewall_rules_for_group(group)
  protocol_selector.set_selected_items(rules.get_blocked_protocols())
  
  ret = None

  while True:

    ret = ycp.UI.UserInput()
    print ret
        
    if response_was(ret, "abort"):
      if ReallyAbort():
        break
      else:
        continue

    elif response_was(ret, 'protocol_remove_all'):

      removed = protocol_selector.remove_all()

      for protocol in removed:
        rules.remove_blocked_protocol(protocol)

      if (len(removed) > 0):
        Education.SetModified(True)

    elif response_was(ret, 'protocol_add_all'):

      added = protocol_selector.add_all()

      for protocol in added:
        rules.add_blocked_protocol(protocol)

      if (len(added) > 0):
        Education.SetModified(True)
      
    elif response_was(ret, 'protocol_remove'):

      removed = protocol_selector.remove()
      rules.remove_blocked_protocol(removed)

      if removed:
        Education.SetModified(True)

    elif response_was(ret, 'protocol_add'):

      added = protocol_selector.add()
      rules.add_blocked_protocol(added)

      if added:
        Education.SetModified(True)

    elif response_was(ret, 'group'):

      protocol_selector.set_available_items(EducationFirewalling.get_protocols_list())
      group = UI.QueryWidget(id('group'), sym('Value'))
      rules = EducationFirewalling.get_firewall_rules_for_group(group)
      protocol_selector.set_selected_items(rules.get_blocked_protocols())
  
    elif response_was(ret, "next") or response_was(ret, "back"):
      break
    
  return ret